import uuid
from datetime import datetime
from fastapi import APIRouter, Depends, Request, HTTPException, Body
from typing import Annotated, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from app import config
from app.services.order import OrderService, ensure_safe_dict
from app.core.db.database import async_get_db
from app.util.jwt_helper import validate_auth_header
from app.schemes.order import OrderCreate, OrderCreateRequest, CreatePayUrlRequest
from app.models.order import OrderStatus
from app.services.user import UserScoreService
from app.schemes.score import UserScoreUpdate
from app.util.pay.pay import alipay
from app.core.pkg.log import logger
from app.core.exceptions.http_exceptions import NotFoundException
import pytz

router_order = APIRouter(tags=["订单服务"], prefix="/order")


def generate_trade_no():
    """生成随机交易号"""
    try:
        # 获取时区对象，而不是时区字符串
        timezone_str = config.get("timezone", default='Asia/Shanghai')
        # 确保获取到的是有效的时区对象
        try:
            tz = pytz.timezone(timezone_str)
        except Exception:
            logger.warning(f"Invalid timezone: {timezone_str}, using default 'Asia/Shanghai'")
            tz = pytz.timezone('Asia/Shanghai')
            
        # 使用时区对象创建带时区的datetime
        current_time = datetime.now(tz).strftime('%Y%m%d%H%M%S')
        random_uuid = str(uuid.uuid4()).replace('-', '')[:8]
        return f"{current_time}{random_uuid}"
    except Exception as e:
        logger.error(f"Error generating trade number: {str(e)}")
        # 保证即使出错也能生成唯一标识，使用不带时区的时间
        return f"{datetime.now().strftime('%Y%m%d%H%M%S')}{uuid.uuid4().hex[:8]}"


@router_order.post("/create", description="创建订单")
async def create_order(request: Request, order_create: OrderCreateRequest,
                       db: Annotated[AsyncSession, Depends(async_get_db)]):
    try:
        # 验证用户是否已登录
        try:
            user_payload_id = validate_auth_header(request)
            if not user_payload_id:
                logger.warning("User authentication failed in order creation")
                return {"success": False, "message": "用户未登录或认证失败", "data": None}
        except Exception as auth_err:
            logger.error(f"Authentication error: {str(auth_err)}")
            return {"success": False, "message": "用户认证错误", "data": None}
            
        # 验证订单金额
        try:
            amount = float(order_create.order_amount)
            if amount <= 0:
                logger.warning(f"Invalid order amount: {amount}")
                return {"success": False, "message": "订单金额必须大于0", "data": None}
        except ValueError:
            logger.warning(f"Invalid order amount format: {order_create.order_amount}")
            return {"success": False, "message": "订单金额格式不正确", "data": None}
            
        # 生成订单交易号
        order_trade_no = generate_trade_no()
        logger.info(f"Generated order trade number: {order_trade_no} for user: {user_payload_id}")
        
        # 创建订单
        order_service = OrderService(db)
        order = OrderCreate(
            payload_id=user_payload_id,
            order_amount=order_create.order_amount,
            description='命格推理支付',
            order_trade_no=order_trade_no
        )
        
        # 尝试保存订单到数据库
        try:
            order = await order_service.create_order(order)
            logger.info(f"Order created successfully: {order_trade_no}")
            return {"success": True, "message": "创建订单成功", "data": order}
        except Exception as db_err:
            logger.error(f"Database error when creating order: {str(db_err)}")
            return {"success": False, "message": "创建订单失败，数据库错误", "data": None}
            
    except Exception as e:
        logger.error(f"Unexpected error in create_order: {str(e)}")
        return {"success": False, "message": "创建订单时发生未知错误", "data": None}


@router_order.post("/create_pay_url", description="创建支付链接")
async def create_pay_url(request: Request, pay_request: CreatePayUrlRequest, db: Annotated[AsyncSession, Depends(async_get_db)]):
    try:
        # 获取订单交易号
        order_trade_no = pay_request.order_trade_no
        
        # 验证参数
        if not order_trade_no or not order_trade_no.strip():
            logger.warning("Empty order trade number provided")
            return {"success": False, "message": "订单交易号不能为空", "data": None}
            
        # 验证用户身份
        try:
            user_payload_id = validate_auth_header(request)
            if not user_payload_id:
                logger.warning("User authentication failed in create_pay_url")
                return {"success": False, "message": "用户未登录或认证失败", "data": None}
        except Exception as auth_err:
            logger.error(f"Authentication error in create_pay_url: {str(auth_err)}")
            return {"success": False, "message": "用户认证错误", "data": None}
        
        # 创建支付链接
        logger.info(f"Creating payment URL for order: {order_trade_no}, user: {user_payload_id}")
        order_service = OrderService(db)
        
        try:
            # 查询订单并生成支付链接
            pay_url = await order_service.create_pay_url(order_trade_no, user_payload_id)
            logger.info(f"Payment URL created successfully for order: {order_trade_no}")
            return {"success": True, "message": "创建支付链接成功", "data": {"pay_url": pay_url}}
        except NotFoundException as nf_err:
            # 处理订单不存在的情况
            logger.warning(f"Order not found: {order_trade_no} for user: {user_payload_id}")
            return {"success": False, "message": str(nf_err), "data": None}
        except Exception as service_err:
            # 处理支付服务错误
            logger.error(f"Error creating payment URL: {str(service_err)}")
            return {"success": False, "message": "创建支付链接失败", "data": None}
    
    except Exception as e:
        # 捕获所有未预期的异常
        logger.error(f"Unexpected error in create_pay_url: {str(e)}")
        return {"success": False, "message": "创建支付链接时发生未知错误", "data": None}


@router_order.get("/callback", description="支付结果页面回调")
async def callback_order(request: Request, db: Annotated[AsyncSession, Depends(async_get_db)], out_trade_no: str = None, trade_status: str = None):
    request_data = dict(request.query_params)
    sign = request_data.pop("sign")

    success = alipay.verify(request_data, sign)
    if not success:
        logger.error("Payment verification failed")
        return "failure"
    logger.error("Payment verification success!")
    return "success"


@router_order.post("/notify", description="支付异步通知")
async def payment_notify(request: Request, db: Annotated[AsyncSession, Depends(async_get_db)]):
    """
    处理支付宝的异步通知回调。这是实际处理支付结果的函数。
    异步通知是在交易状态发生变更后，支付宝服务器主动发送的POST请求。
    {
        'gmt_create': '2025-04-14 22:51:10',
        'charset': 'utf-8',
        'gmt_payment': '2025-04-14 22:51:14',
        'notify_time': '2025-04-14 22:51:15',
        'subject': '命格推理支付',
        'sign': 'b/KkZAO1WtCa9qWOaRo+qWpt1URbxTpXBk9VIPKIV0zZKfKJX5V9UTkP8BTaR8A8/6r4LQyi8IvLRSl73IbiezYsCvsGhJNIjFRfl6YrvBkYeLDLJ6I8aLTHzZOQn/QLbHuLnS66Y2cmv/GsAvABWNsT9xegMp8ly3ODLOsBMdAbL+Pgx539izTEC55g1i9o4qosANaZVNY1IDVr5K5zybrXaxLuRlUhJNhR1rTF+nS54rFarjep4YLuY488cOTs53lT2K+86W1V/tyL5Yvd9Zh4bIgJkiY8ofkYVt+5VD93Y+xUra84DC533P24TcZH6PGrIQD43veN23xGKhed7g==',
        'buyer_id': '2088902910857469',
        'invoice_amount': '5.00',
        'version': '1.0',
        'notify_id': '2025041401222225115057461470820490',
        'fund_bill_list': '[{"amount":"5.00","fundChannel":"ALIPAYACCOUNT"}]', 
        'notify_type': 'trade_status_sync', 
        'out_trade_no': '20250414225059d48ee0ae', 
        'total_amount': '5.00', 
        'trade_status': 'TRADE_SUCCESS', 
        'trade_no': '2025041422001457461443404138', 
        'auth_app_id': '2021005137662938', 
        'receipt_amount': '5.00', 
        'point_amount': '0.00', 
        'buyer_pay_amount': '5.00', 
        'app_id': '2021005137662938', 
        'sign_type': 'RSA2', 
        'seller_id': '2088212942111223'
    }
    """

    # 获取支付宝回调参数
    try:
        data = await request.form()
        payment_data = dict(data)
        logger.info(f"Payment async notification received: {payment_data}")
        
        # 验证支付宝回调签名
        try:
            # 支付宝回调验证
            signature_verified = alipay.verify(payment_data, payment_data.pop("sign", ""))
            if not signature_verified:
                logger.error("Payment signature verification failed")
                # 根据支付宝规范，如果验证失败，返回"failure"字符串
                return "failure"
        except Exception as e:
            logger.error(f"Payment verification error: {str(e)}")
            return "failure"
        
        # 获取订单交易号
        order_trade_no = payment_data.get("out_trade_no")
        if not order_trade_no:
            logger.error("Order trade number not found in callback")
            return "failure"
        
        # 获取订单信息
        order_service = OrderService(db)
        order = await order_service.order_service.get(db, order_trade_no=order_trade_no)
        if not order:
            logger.error(f"Order not found: {order_trade_no}")
            return "failure"
        
        # 检查订单是否已经处理过
        if order.get("order_status") == OrderStatus.PAID:
            logger.info(f"Order already processed: {order_trade_no}")
            # 如果订单已处理，返回success避免重复处理
            return "success"
        
        # 更新订单状态为已支付
        payment_amount = payment_data.get("total_amount")

        # 获取时区对象
        timezone_str = config.get("timezone", default='Asia/Shanghai')
        try:
            tz = pytz.timezone(timezone_str)
        except Exception:
            logger.warning(f"Invalid timezone: {timezone_str}, using default 'Asia/Shanghai'")
            tz = pytz.timezone('Asia/Shanghai')
            
        # 更新订单状态
        update_data = {
            "order_status": OrderStatus.PAID,
            "updated_at": datetime.now(tz)
        }
        safe_update_data = ensure_safe_dict(update_data)
        
        try:
            await order_service.order_service.update(
                db, 
                order_trade_no=order_trade_no, 
                object=safe_update_data
            )
            
            # 获取用户ID
            user_id = order.get("payload_id")
            
            # 增加用户积分（假设支付金额与积分1:20对应）
            score_money_mapping = {
                "5.00": 20,
                "10.00": 40,
                "20.00": 80,
                "25.00": 100,
            }
            points_to_add = score_money_mapping[str(payment_amount)]
            user_score_service = UserScoreService(db)
            
            # 获取用户当前积分
            user_score = await user_score_service.get_user_score(user_id)
            
            if user_score:
                # 更新用户积分
                score_update_data = {
                    "total_score": user_score.get("total_score") + points_to_add,
                    "updated_at": datetime.now(tz)
                }
                safe_score_update_data = ensure_safe_dict(score_update_data)
                
                await user_score_service.user_score_service.update(
                    db,
                    payload_id=user_id,
                    object=safe_score_update_data
                )
            else:
                # 创建用户积分记录
                await user_score_service.create_user_score({
                    "payload_id": user_id,
                    "total_score": points_to_add,
                    "used_score": 0
                })
            
            logger.info(f"Order {order_trade_no} processed successfully, added {points_to_add} points to user {user_id}")
            
            # 根据支付宝规范，处理成功返回"success"字符串
            return "success"
            
        except Exception as e:
            logger.error(f"Error processing payment callback: {str(e)}")
            return "failure"
            
    except Exception as e:
        logger.error(f"Unexpected error in payment_notify: {str(e)}")
        return "failure"
